package com.tyqx.hashchainbiz.controller.wx.accountFirm;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.tyqx.hashchainbean.module.HashIndex;
import com.tyqx.hashchainbean.module.WxAccountFirmVerification;
import com.tyqx.hashchainbean.module.WxAccountFirmVerificationRelation;
import com.tyqx.hashchainbean.vo.BlockChainVO;
import com.tyqx.hashchainbean.vo.MerkleRootVO;
import com.tyqx.hashchainbean.vo.MongoDbInfoVO;
import com.tyqx.hashchainbiz.service.HashIndexService;
import com.tyqx.hashchainbiz.service.MysqlDataBaseAndMongDbConfigService;
import com.tyqx.hashchainbiz.service.WxAccountFirmVerificationRelationService;
import com.tyqx.hashchainbiz.service.WxAccountFirmVerificationService;
import com.tyqx.hashchaindao.mapper.WxAccountFirmVerificationMapper;
import com.tyqx.hashchainutil.common.BlockData;
import com.tyqx.hashchainutil.common.CryptoUtil;
import com.tyqx.hashchainutil.common.mongodb.ImagePathHashValueUtil;
import com.tyqx.hashchainutil.org.app.util.Util;
import hashchainutil.common.*;
import org.hyperledger.fabric.sdk.security.CryptoPrimitives;
import org.json.JSONObject;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.nio.file.Path;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("/wx/wxAccountFirmVerification")
@CrossOrigin
public class WxAccountFirmVerificationController {


    @Resource
    private MysqlDataBaseAndMongDbConfigService mysqlDataBaseAndMongDbConfigService;

    @Resource
    private WxAccountFirmVerificationService wxAccountFirmVerificationService;

    @Resource
    private WxAccountFirmVerificationRelationService wxAccountFirmVerificationRelationService;

    @Resource
    private HashIndexService hashIndexService;

    @Resource
    private MongoTemplate mongoTemplate;

    @RequestMapping(value = "/insertHashValue", method = RequestMethod.POST)
    @ResponseBody
    public Dto insertHashValue(@RequestBody WxAccountFirmVerification wxAccountFirmVerification, HttpServletRequest request) throws Exception {
        Date currentDate = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date createTime = sdf.parse(sdf.format(currentDate));
        Date updateTime = createTime;
        String msg = "";
        MongoDbInfoVO mongoDbInfoVO = new MongoDbInfoVO();
        if (EmptyUtils.isNotEmpty(wxAccountFirmVerification)) {
            wxAccountFirmVerification.setStatus("0");
            wxAccountFirmVerification.setType("0");
            Gson gson = new GsonBuilder()
                    .setDateFormat("yyyy-MM-dd HH:mm:ss")
                    .create();
            String wxAccountFirmVerificationListStr = gson.toJson(wxAccountFirmVerification);
            CryptoPrimitives suite = new CryptoPrimitives();
            suite.init();
            String hashValue = ImagePathHashValueUtil.getHashValue(wxAccountFirmVerificationListStr, suite);
            List<WxAccountFirmVerification> wxAccountFirmVerificationList = new ArrayList<>();
            wxAccountFirmVerificationList.add(wxAccountFirmVerification);
            mongoDbInfoVO.setHashValue(hashValue);
            mongoDbInfoVO.setInfoList(wxAccountFirmVerificationList);
            mongoDbInfoVO.setInfoTableName("wx_account_firm_verification");

            String collName = "wxAccountFirmVerification";

            mysqlDataBaseAndMongDbConfigService.insertDataMongoDB(collName, mongoDbInfoVO);
        }

        if (EmptyUtils.isNotEmpty(mongoDbInfoVO.getId())) {
            msg = "签名成功";
            return DtoUtil.returnSuccess(msg);
        } else {
            msg = "签名失败";
            return DtoUtil.returnFail(msg, "100001");
        }
    }

    @RequestMapping(value = "/batchInsertHashValue", method = RequestMethod.POST)
    @ResponseBody
    public Dto batchInsertHashValue(@RequestBody List<WxAccountFirmVerification> wxAccountFirmVerificationList, HttpServletRequest request) throws Exception {
        Date currentDate = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date createTime = sdf.parse(sdf.format(currentDate));
        Date updateTime = createTime;
        String msg = "";
        MongoDbInfoVO mongoDbInfoVO = new MongoDbInfoVO();
        if (wxAccountFirmVerificationList.size() > 0) {
            Gson gson = new GsonBuilder()
                    .setDateFormat("yyyy-MM-dd HH:mm:ss")
                    .create();
            String wxAccountFirmVerificationListStr = gson.toJson(wxAccountFirmVerificationList);
            CryptoPrimitives suite = new CryptoPrimitives();
            suite.init();
            String hashValue = ImagePathHashValueUtil.getHashValue(wxAccountFirmVerificationListStr, suite);

            mongoDbInfoVO.setHashValue(hashValue);
            mongoDbInfoVO.setInfoList(wxAccountFirmVerificationList);
            mongoDbInfoVO.setInfoTableName("wx_account_firm_verification");

            String collName = "wxAccountFirmVerification";

            mysqlDataBaseAndMongDbConfigService.insertDataMongoDB(collName, mongoDbInfoVO);
        }

        if (EmptyUtils.isNotEmpty(mongoDbInfoVO.getId())) {
            msg = "信息上链成功";
            return DtoUtil.returnSuccess(msg);
        } else {
            msg = "信息上链失败";
            return DtoUtil.returnFail(msg, "100001");
        }
    }



    @RequestMapping(value = "/verifyData", method = RequestMethod.POST,
            produces = "application/json")
    @ResponseBody
    public Dto verifyDataYinyue(@RequestBody WxAccountFirmVerification wxAccountFirmVerification, HttpServletRequest request) throws Exception {
        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .create();
        CryptoPrimitives suite = new CryptoPrimitives();
        suite.init();

        String msg = "";
        Long orgIndex = 0L;
        String caType = "msp";
        String channelName = "hashchainchannel";
        try {
            if(EmptyUtils.isNotEmpty(wxAccountFirmVerification)) {
                String jsonString = gson.toJson(wxAccountFirmVerification);
                JSONObject jsonObject1 = new JSONObject(jsonString);

                String userName=wxAccountFirmVerification.getCreateId();
                jsonObject1 = JsonUtil.getSortJson(jsonObject1);
                String jsonObject2 = jsonObject1.toString();
                byte[] hashBytes = suite.hash(jsonObject2.getBytes());

                String hashValue = Base64.getEncoder().encodeToString(hashBytes);

                List<HashIndex> hashIndexList = hashIndexService.getHashIndexByHashValue(hashValue);
                HashIndex hashIndex = null;
                if (hashIndexList.size() > 0) {
                    hashIndex = hashIndexList.get(0);
                } else {
                    return DtoUtil.returnFail("未查询到该交易", "100002");
                }

                BlockData blockData = new BlockData();
                Map<String, String> map = blockData.getBlockByNum(hashIndex.getBlockNum(), channelName);
                String blockDataStr = map.get("blockDataStr");
                String blockNum = map.get("blockNum");
                JsonObject blockDataJson = new JsonParser().parse(blockDataStr).getAsJsonObject();
                JsonObject hashItemJson = blockData.getHashItemByTxId(blockDataJson, hashIndex.getTxId());
                String blockHashValue = hashItemJson.get("hashValue").toString();

                blockHashValue = blockHashValue.substring(blockHashValue.indexOf("\"") + 1, blockHashValue.lastIndexOf("\""));
                String blockHashSignature = hashItemJson.get("hashSignature").toString();
                blockHashSignature = blockHashSignature.substring(blockHashSignature.indexOf("\"") + 1, blockHashSignature.lastIndexOf("\""));


                Map<String, Object> pathMap = Util.readUserContext(caType, userName, orgIndex);
                //Path caPath = (Path) pathMap.get("caPath");
                Path clientCertPath = (Path) pathMap.get("clientCertPath");
                //Path clientKeyPath = (Path) pathMap.get("clientKeyPath");

                CryptoUtil cryptoUtil = new CryptoUtil();

                boolean flag = cryptoUtil.verify(clientCertPath, blockHashSignature, blockHashValue,mongoTemplate);

                String collectionName = "merkleRoot";

                List<String> hashValueList = new ArrayList<>();

                Criteria criteria = Criteria.where("rootHashValue").is(blockHashValue);
                Query query = Query.query(criteria);
                List<MerkleRootVO> MerkleRootVO = mongoTemplate.find(query, com.tyqx.hashchainbean.vo.MerkleRootVO.class, collectionName);
            /*if (MerkleRootVO.size() > 0) {
                hashValueList = MerkleRootVO.get(0).getHashValueList();
            } else {
                hashValueList = hashIndexService.getHashValueList(blockHashValue);
                if (hashValueList.size() > 0) {
                    MerkleRootVO merkleRootVO = new MerkleRootVO();
                    merkleRootVO.setHashValueList(hashValueList);
                    merkleRootVO.setRootHashValue(blockHashValue);
                    mongoTemplate.insert(merkleRootVO, "merkleRoot");
                }
            }

            String rootHashValue = MerkleUtil.getMerkleRoot(hashValueList, suite);*/

                List<List<String>> merkleTree=new ArrayList<>();

                if (MerkleRootVO.size() > 0) {
                    merkleTree = MerkleRootVO.get(0).getMerkleTree();
                } else {
                    hashValueList = hashIndexService.getHashValueList(blockHashValue);
                    merkleTree = MerkleUtil.computeMerkleTree(hashValueList, suite);
                    if (merkleTree.size() > 0) {
                        com.tyqx.hashchainbean.vo.MerkleRootVO merkleRootVO = new MerkleRootVO();
                        //merkleRootVO.setHashValueList(hashValueList);
                        merkleRootVO.setMerkleTree(merkleTree);
                        merkleRootVO.setRootHashValue(blockHashValue);
                        mongoTemplate.insert(merkleRootVO, "merkleRoot");
                    /*long flag1=mongoTemplate.count(new Query(),"merkleRoot");
                    if(flag1>0){

                    }*/
                    }
                }
                boolean varifyResult = MerkleUtil.verifyMerkleTree(merkleTree, hashValue, suite);
                //String rootHashValue = MerkleUtil.getMerkleRoot(hashValueList, suite);

                if (varifyResult  && flag) {
                    BlockChainVO blockChainVO=new BlockChainVO();
                    blockChainVO.setTxId(hashIndex.getTxId());
                    blockChainVO.setHashValue(blockHashValue);
                    blockChainVO.setBlockNum(blockNum);
                    blockChainVO.setTxTimeStamp(hashIndex.getTxTimeStamp());
                    blockChainVO.setUserName(userName);

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String txTimeStamp = sdf.format(hashIndex.getTxTimeStamp());

                    String successMsg="验证区块链成功,数据位于区块:"+blockNum+",上链时间:"+txTimeStamp+",数据签名人:"+userName;
                    return DtoUtil.returnSuccess(successMsg);
                } else {
                    return DtoUtil.returnFail("验证区块链失败", "100001");
                }
            }else{
                return DtoUtil.returnFail("验证区块链失败", "100002");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return DtoUtil.returnFail("验证区块链错误", "100003");
        }
    }


    @RequestMapping(value = "/insertVerificationAndRelation", method = RequestMethod.POST)
    @ResponseBody
    public Dto insertVerificationAndRelation(@RequestBody WxAccountFirmVerificationRelation wxAccountFirmVerificationRelation) throws Exception {
        Date currentDate = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date createTime = sdf.parse(sdf.format(currentDate));


        WxAccountFirmVerification wxAccountFirmVerification = new WxAccountFirmVerification();
        wxAccountFirmVerification.setStatus("0");
        wxAccountFirmVerification.setType("0");
        wxAccountFirmVerification.setBank("");
        wxAccountFirmVerification.setBankAccount("");
        wxAccountFirmVerification.setContributedDay("");
        wxAccountFirmVerification.setContributedMonth("");
        wxAccountFirmVerification.setContributedYear("");
        wxAccountFirmVerification.setCreateDate(createTime);
        wxAccountFirmVerification.setCreateId(wxAccountFirmVerificationRelation.getCreateId());
        wxAccountFirmVerification.setCurrency("");
        wxAccountFirmVerification.setEndDay("");
        wxAccountFirmVerification.setEndMonth("");
        wxAccountFirmVerification.setEndYear("");
        wxAccountFirmVerification.setNatureAccount("");
        wxAccountFirmVerification.setMoney("");
        wxAccountFirmVerification.setPayer("");
        wxAccountFirmVerification.setRemarks("");
        wxAccountFirmVerification.setHashValue("");
        wxAccountFirmVerification.setRootHashValue("");
        wxAccountFirmVerification.setSourceFunds("");
        wxAccountFirmVerification.setSourceFundsInput("");
        wxAccountFirmVerification.setSubBranch("");
        wxAccountFirmVerification.setUseFunds("");

        wxAccountFirmVerificationRelation.setCreateDate(createTime);
        Integer flag = mysqlDataBaseAndMongDbConfigService.addVerificationAndRelation(wxAccountFirmVerification,wxAccountFirmVerificationRelation);
        if(flag>0){
            return DtoUtil.returnSuccess("提交受查企业成功");
        }else{
            return DtoUtil.returnSuccess("提交受查企业失败");
        }
    }


    @RequestMapping(value = "/queryByAccountFirmId", method = RequestMethod.POST)
    @ResponseBody
    public Dto queryByAccountFirmId(Integer accountFirmId){
        List<WxAccountFirmVerification> wxAccountFirmVerificationList = wxAccountFirmVerificationService.queryByAccountFirmId(accountFirmId);
        if(wxAccountFirmVerificationList.size()>0){
            return DtoUtil.returnSuccess("查询发送验资业务成功",wxAccountFirmVerificationList);
        }else{
            return DtoUtil.returnSuccess("未查到发送验资业务记录");
        }
    }

    @RequestMapping(value = "/queryByToAccountFirmId", method = RequestMethod.POST)
    @ResponseBody
    public Dto queryByToAccountFirmId(Integer toAccountFirmId){
        List<WxAccountFirmVerification> wxAccountFirmVerificationList = wxAccountFirmVerificationService.queryByToAccountFirmId(toAccountFirmId);
        if(wxAccountFirmVerificationList.size()>0){
            return DtoUtil.returnSuccess("查询接收验资业务成功",wxAccountFirmVerificationList);
        }else{
            return DtoUtil.returnSuccess("未查到接收验资业务记录");
        }
    }

    @RequestMapping(value = "/updateStatus", method = RequestMethod.POST)
    @ResponseBody
    public Dto updateStatus(Integer id,String status){
        Integer flag = wxAccountFirmVerificationService.updateStatus(id,status);
        if(flag>0){
            return DtoUtil.returnSuccess("确认成功");
        }else{
            return DtoUtil.returnSuccess("确认失败");
        }
    }
}
